package org.btik.light.server.platform.manage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.btik.context.AppContext;
import org.btik.context.event.SystemStartHook;
import org.btik.context.thread.SystemControlAble;
import org.btik.light.meta.DevMo;
import org.btik.light.meta.DevState;
import org.btik.light.meta.base.Report;
import org.btik.light.meta.event.DevEventListener;
import org.btik.light.meta.event.DevReportEventHandler;
import org.btik.light.server.platform.event.ConnectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author lustre
 * @version 1.0
 * @since 2021/5/15 12:37
 * 设备事件消费和转发器
 */
@Component
public class DevEventDispatcher extends Thread implements SystemControlAble, SystemStartHook {

    private final Log log = LogFactory.getLog(DevEventDispatcher.class);

    private final ShutDownRunnable shutDown = new ShutDownRunnable();

    private List<DevEventListener> devEventListeners;

    private List<DevReportEventHandler> devReportEventHandlers;

    private final LinkedBlockingQueue<Runnable> handles = new LinkedBlockingQueue<>();

    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                Runnable take = handles.take();
                if (take instanceof ShutDownRunnable) {
                    log.info(((ShutDownRunnable) take).msg);
                    break;
                }
                try {
                    take.run();
                } catch (Exception e) {
                    log.warn(" ", e);
                }
            } catch (InterruptedException e) {
                log.info("", e);
            }
        }
    }

    public void onDisconnect(String sn) {
        handles.add(() -> {
            for (DevEventListener devEventListener : devEventListeners) {
                devEventListener.onConnected(new ConnectEvent(sn, DevState.CONNECTED));
            }
        });
    }

    public void onConnect(DevMo devMo) {
        handles.add(() -> {
            for (DevEventListener devEventListener : devEventListeners) {
                devEventListener.onConnected(new ConnectEvent(devMo, DevState.CONNECTED));
            }
        });
    }

    public void onMessage(Report report) {
        handles.add(() -> {
            for (DevReportEventHandler devReportEventHandler : devReportEventHandlers) {
                devReportEventHandler.onMessage(report);
            }
        });
    }

    @Override
    public void shutdown(String msg) {
        shutDown.msg = msg;
        handles.add(shutDown);
    }

    @Override
    public void onSystemStart(AppContext appContext) {
        this.devEventListeners = appContext.getBeans(DevEventListener.class);
        this.devReportEventHandlers = appContext.getBeans(DevReportEventHandler.class);
    }

    static class ShutDownRunnable implements Runnable {
        private String msg;

        @Override
        public void run() {

        }
    }

    public DevEventDispatcher() {
        setName("DevEventDispatcher-" + getId());
    }
}
